﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.WebControls;
using Slam.FieldTypes;
using Slam.SharePoint;
using SlamCms.Data;
using SlamCms.Common;
using SlamCms.SharePoint.Core;
using SlamCms.SharePoint.Tagging.Services;
using Slam;
using SlamCms.SharePoint.SlamProfiles.ContentItem;
using SlamCms.SharePoint.FieldTypes;

namespace SlamCms.SharePoint.Tagging.FieldTypes
{
	public partial class TagFieldControl : SlamCmsFieldControl
	{
		protected Literal ltTitle;
		protected HtmlGenericControl editTagsArea;
		protected Panel pnlModalDisplay;
		protected HtmlGenericControl tagListing;
		protected HtmlGenericControl editModalLink;
		protected HtmlGenericControl tagModal;
		protected TagTreeView tvTagHierarchy;
		protected Button btnCancel;
		protected Button btnOk;
		protected HiddenField hdnDefaultValue;
		protected HtmlAnchor editTags;
		protected HtmlGenericControl tagModalList;
		protected Literal ltCategoryHandle;
		protected HiddenField hdnSelectedTagIds;

		protected Panel pnlCheckboxDisplay;
		protected Repeater rptCheckList;

		protected Panel pnlDropDownDisplay;
		protected DropDownList ddlTags;

		protected HtmlGenericControl errors;
		protected HiddenField hdnValueField;

		protected HtmlGenericControl displayTagsArea;
		protected Literal ltDisplayTags;

		private ContentItem _contentItem;
		private ContentItem ContentItem
		{
			get
			{	
				return GetContentItem(ListItem);
			}
		}

		private ContentType _contentType;
		private ContentType ContentType
		{
			get
			{
				if (String.IsNullOrEmpty(SlamContentType))
					LoadSlamPropertiesForItem();

				if (HttpContext.Current.Items["CurrentTagFieldControlContentType"] == null)
				{
					_contentType = SlamCmsContext.Data.ContentTypes.Where(c => c.Title.Equals(SlamContentType, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
					if (_contentType != null && _contentType.DefaultTags == null)
						_contentType.DefaultTags = new List<Tag>();

					HttpContext.Current.Items["CurrentTagFieldControlContentType"] = _contentType;
				}
				_contentType = HttpContext.Current.Items["CurrentTagFieldControlContentType"] as ContentType;
				return _contentType;
			}
		}

		private IEnumerable<SlamCms.Data.TagTreeNode> _defaultTagTreeNodes;
		private IEnumerable<SlamCms.Data.TagTreeNode> DefaultTagTreeNodes
		{
			get
			{
				if (_defaultTagTreeNodes == null)
				{
					var siteOrListDefaults = SlamCmsContext.Data.SiteOrListDefaults.Where(d => !String.IsNullOrEmpty(d.SiteListUrl) ? (d.SiteListUrl.Contains(Web.ServerRelativeUrl) || d.SiteListUrl.Contains(List.RootFolder.ServerRelativeUrl)) : false);
					List<string> tagIdentifiers = new List<string>();
					foreach (var siteOrListDefault in siteOrListDefaults)
					{
						if(siteOrListDefault.DefaultTags != null)
							tagIdentifiers.AddRange(siteOrListDefault.DefaultTags.Select(t => t.Identifier));
					}
					if (tagIdentifiers.Count > 0)
					{
						_defaultTagTreeNodes = TagTree.FindNodes(n => !String.IsNullOrEmpty(n.Identifier) ? n.Identifier.In(tagIdentifiers.ToArray()) : false);
					}
					else
					{
						_defaultTagTreeNodes = new List<SlamCms.Data.TagTreeNode>();
					}
				}
				return _defaultTagTreeNodes;
			}
		}

		private IEnumerable<SlamCms.Data.TagTreeNode> _itemTagTreeNodes;
		private IEnumerable<SlamCms.Data.TagTreeNode> ItemTagTreeNodes
		{
			get
			{
				if (_itemTagTreeNodes == null && ContentItem != null)
				{
					string[] tagIdentifiers = ContentItem.Tags.Select(t => t.Identifier).ToArray();
					if (tagIdentifiers.Length > 0)
					{
						_itemTagTreeNodes = TagTree.FindNodes(n => !String.IsNullOrEmpty(n.Identifier) ? n.Identifier.In(tagIdentifiers) : false);
					}
				}

				if(_itemTagTreeNodes == null)
					_itemTagTreeNodes = new List<SlamCms.Data.TagTreeNode>();

				return _itemTagTreeNodes;
			}
		}

		private TagTree _tagTree;
		private TagTree TagTree
		{
			get
			{
				if (_tagTree == null)
				{
					
					_tagTree = SlamCmsContext.Data.GetTagTree(Zone.ZoneId).
						FilterTagCategories(new string[] { TagCategoryId }).
						Localize(SlamCmsContext.User.Language).
						FilterTagScope(ContentType.Title);

					string[] tagIdentifiers = new string[]{};
					if (SlamCmsContext.User.Groups != null && SlamCmsContext.User.Groups.Any(g => g.Name.Equals(Constants.GroupNames.GlobalTagOwner)))
					{
						tagIdentifiers = _tagTree.FindNodes(n => !String.IsNullOrEmpty(n.Identifier)).Select(t => t.Identifier).ToArray();
					}
					else if (SlamCmsContext.User.OwnedTags != null)
					{
						tagIdentifiers = SlamCmsContext.User.OwnedTags.Select(t => t.Identifier).ToArray();
					}

					if(tagIdentifiers.Length > 0)
						_tagTree = _tagTree.SetRestrictAccessForTags(tagIdentifiers, false);
				}
				return _tagTree;
			}
		}

		private Zone _zone;
		private Zone Zone
		{
			get
			{
				if (_zone == null)
				{
					_zone = SlamCmsContext.Data.Zones.Where(z => z.Sites.Any(s => s.SiteId == Web.ID)).FirstOrDefault();
				}

				if (_zone == null)
				{
					_zone = SlamCmsContext.Data.Zones.FirstOrDefault();
				}
				return _zone;
			}
		}

		public TagFieldDisplayMode DisplayMode
		{
			get;
			set;
		}

		public string TagCategoryId
		{
			get;
			set;
		}

		public bool DefaultRequired
		{
			get;
			set;
		}

		protected override string DefaultTemplateName
		{
			get { return "SlamCMSTagFieldControlTemplate"; }
		}

		public override string DisplayTemplateName
		{
			get
			{
				return "SlamCMSTagFieldControlDisplayTemplate";
			}
			set
			{
				base.DisplayTemplateName = value;
			}
		}

		private TaggingServices _fieldServices;
		private TaggingServices FieldServices
		{
			get
			{
				if (_fieldServices == null)
				{
					_fieldServices = new TaggingServices();
				}
				return _fieldServices;
			}
		}

		private string SlamContentType
		{
			get;
			set;
		}

		private string SlamId
		{
			get;
			set;
		}

		public override object Value
		{
			get
			{
				EnsureChildControls();
				string returnValue = "";
				if (SelectedTagTreeNodes.Count() > 0)
				{
					switch (DisplayMode)
					{
						case TagFieldDisplayMode.Invisible:
							returnValue = Convert.ToString(ItemFieldValue ?? hdnValueField.Value);
							break;
						default:
							returnValue = String.Join(", ", SelectedTagTreeNodes.Select(n => String.IsNullOrEmpty(n.Text) ? n.Identifier : n.Text).ToArray());
							break;
					}
				}
				return returnValue;
			}
			set
			{
				EnsureChildControls();

				if (value != null && value.ToString().Contains(";#"))
				{
					hdnValueField.Value = value.ToString();
				}
			}
		}

		private IEnumerable<SlamCms.Data.TagTreeNode> _selectedTags;
		public IEnumerable<SlamCms.Data.TagTreeNode> SelectedTagTreeNodes
		{
			get
			{
				
				if (_selectedTags == null)
				{
					_selectedTags = new List<SlamCms.Data.TagTreeNode>();
				}

				if(_selectedTags.Count() == 0)
				{	
					List<int> selectedTagIds = new List<int>();

					switch (DisplayMode)
					{
						case TagFieldDisplayMode.CheckBoxes:
							foreach (RepeaterItem item in rptCheckList.Items)
							{
								CheckBox chkTag = item.FindControl("chkTag") as CheckBox;
								HiddenField chkTagValue = item.FindControl("chkTagValue") as HiddenField;
								if (chkTag.Checked)
								{
									selectedTagIds.Add(Int32.Parse(chkTagValue.Value));
								}
							}
							break;
						case TagFieldDisplayMode.DropDown:
							if ((!Field.Required && ddlTags.SelectedIndex > -1) || (Field.Required && ddlTags.SelectedIndex > 0))
							{
								selectedTagIds.Add(Int32.Parse(ddlTags.SelectedValue));
							}
							break;
						default:
							for (int i = 0; i < tvTagHierarchy.CheckedNodes.Count; i++)
							{
								TreeNode node = tvTagHierarchy.CheckedNodes[i];
								selectedTagIds.Add(Int32.Parse(node.Value));
							}
							break;
					}
					if (selectedTagIds.Count > 0)
					{
						_selectedTags = TagTree.FindNodes(n => n.Tag != null ? n.Tag.ListRelativeId.In(selectedTagIds) : false);
					 	HttpContext.Current.Items[FieldName + "TagFieldValue"] = _selectedTags;
					}
				}

				return _selectedTags;
			}
		}

		private ContentItem GetContentItem(SPListItem listItem)
		{
			if (HttpContext.Current.Items["CurrentTagFieldControlContentItem"] == null)
			{
				HttpContext.Current.Items["CurrentTagFieldControlContentItem"] = SlamCmsContext.Data.CreateQuery().FilterStatus(FilterStatus.None).FilterZone(Zone.ZoneId).Filter("ContentItem.ContentItemID = '{0}'", SlamId).IncludeTags().Cache(QueryCacheBehavior.NoCache).Get().FirstOrDefault();
			}
			_contentItem = HttpContext.Current.Items["CurrentTagFieldControlContentItem"] as ContentItem;
			return _contentItem;
		}

		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);
			Slam.SlamContext.Get(List).Actions.Register(SlamEvent.PreSave, listItem =>
			{
				if (listItem != null)
				{
					string status = listItem.GetPublishingStatus();
					if (status != SlamProfiles.ContentItem.ContentItemStatus.Live.Name)
					{
						HttpContext.Current.Items["CurrentTagFieldControlContentItem"] = null;
						SlamId = Convert.ToString(listItem.GetUniqueId(false, false));
						if (GetContentItem(listItem) != null)
						{
							ClearTags(SlamId);
						}
					}
				}
			});

			Slam.SlamContext.Get(List).Actions.Register(SlamEvent.PostSave, 40, listItem =>
			{
				if (listItem != null)
				{
					string status = listItem.GetPublishingStatus();
					if (status == SlamProfiles.ContentItem.ContentItemStatus.Live.Name)
					{
						HttpContext.Current.Items["CurrentTagFieldControlContentItem"] = null;
						SlamId = Convert.ToString(listItem.GetUniqueId(false, false));
						if (GetContentItem(listItem) != null)
						{
							ClearTags(SlamId);
						}
					}
				}
			});

			Slam.SlamContext.Get(List).Actions.Register("TagFieldControl.SaveTags" + TagCategoryId, SlamEvent.PostSave, 50, listItem =>
			{
				if (listItem != null)
				{
					HttpContext.Current.Items["CurrentTagFieldControlContentItem"] = null;
					SlamId = Convert.ToString(listItem.GetUniqueId(false, false));
					if (GetContentItem(listItem) != null)
					{
						SaveTags(SlamId);
					}
				}
			});

			Slam.SlamContext.Get(List).Actions.Register(SlamEvent.PostSave, 51, listItem =>
			{
				if (listItem != null)
				{
					HttpContext.Current.Items["CurrentTagFieldControlContentItem"] = null;
					SlamId = Convert.ToString(listItem.GetUniqueId(false, false));
					if (GetContentItem(listItem) != null)
					{	
						//SlamCmsContext.Data.Cache.InvalidateUsers();
						SlamCmsContext.Data.Cache.InvalidateCore();
						SlamCmsContext.Data.Cache.InvalidateTags();
					}
				}
			});
		}

		private void ClearTags(string contentItemId)
		{
			SlamCmsContext.Data.Database.ExecuteNonQuery(SlamCms.SharePoint.Data.Queries.TagField.ClearContentItemTags.F(contentItemId));
		}

		private void SaveTags(string contentItemId)
		{
			IEnumerable<SlamCms.Data.TagTreeNode> selectedTags = HttpContext.Current.Items[FieldName + "TagFieldValue"] as IEnumerable<SlamCms.Data.TagTreeNode>;
			if (selectedTags != null)
			{
				var currentTags = SlamCmsContext.Data.Database.ExecuteReader<SlamCms.SharePoint.Data.ContentItemTag>(SlamCms.SharePoint.Data.Queries.TagField.GetContentItemTags.F(contentItemId)).ToList();
				
				foreach (var selectedTag in selectedTags)
				{	
					SlamCmsContext.Data.Database.ExecuteNonQuery(SlamCms.SharePoint.Data.Queries.TagField.InsertContentItem.F(contentItemId, selectedTag.Tag.TagId));
				}
			}
		}

		[SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
		public override void Validate()
		{	
			tagListing.InnerHtml = Convert.ToString(Value);

			if (((base.ControlMode != SPControlMode.Display) && base.IsValid && base.Field.Required) && (tagListing.InnerHtml != null))
			{
				base.Validate();
				errors.Visible = false;
				if (String.IsNullOrEmpty(tagListing.InnerHtml) && DisplayMode != TagFieldDisplayMode.Invisible && DisplayMode != TagFieldDisplayMode.Uneditable)
				{
					base.IsValid = false;
					base.ErrorMessage = SPResource.GetString("MissingRequiredField", new object[0]);
				}
			}
		}

		private void SetFieldControlValue(object value)
		{
			if (value != null && (String.IsNullOrEmpty(hdnValueField.Value) || hdnValueField.Value != value.ToString()))
			{
				hdnValueField.Value = value.ToString();
			}
		}

		private void AddCssIncludes()
		{
			bool addCssReference = true;
			string cssInclude = String.Format("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\" media=\"all\" />", ResolveUrl("~/_layouts/1033/STYLES/SlamCms.Tagging.css"));

			foreach (Control control in Page.Header.Controls)
			{
				if (control is LiteralControl && ((LiteralControl)control).Text == cssInclude)
				{
					addCssReference = false;
				}
			}
			if (addCssReference)
			{
				Page.Header.Controls.Add(new LiteralControl(cssInclude));
			}
		}

		private void AddJavascriptIncludes()
		{
			Page.ClientScript.RegisterClientScriptInclude("jquery", ResolveUrl("~/_layouts/inc/jquery-1.6.2.min.js"));
		}

		private void AddHideControlJavascript(string controlId)
		{
			Page.ClientScript.RegisterStartupScript(GetType(), "hide" + controlId, "$('#" + controlId + "').parents('tr:first').hide(); ", true);
		}

		private void LoadSlamPropertiesForItem()
		{	
			SlamCmsContext.SharePoint.WithElevatedPrivileges().
				SiteCollection(Web.Site.ID).
				Site(Web.ID).
				List(ListId).
				NewItem(elevatedListItem =>
			{
				elevatedListItem["ContentTypeId"] = Item["ContentTypeId"];
				elevatedListItem["SLAM ID"] = Item["SLAM ID"];

				if (Page.Request.QueryString["ContentTypeId"] != null && Page.Request.QueryString["ContentTypeId"] != Convert.ToString(elevatedListItem["ContentTypeId"]))
				{
					elevatedListItem["ContentTypeId"] = Page.Request.QueryString["ContentTypeId"];
				}

				SlamContentType = FieldServices.GetScopeForListItem(elevatedListItem);
				if (SlamContentType.IsNullOrEmpty() && elevatedListItem.ContentType != null)
					SlamContentType = elevatedListItem.ContentType.Name;

				if (elevatedListItem["SLAM ID"] != null)
					SlamId = Convert.ToString(elevatedListItem["SLAM ID"]);
			});
		}

		protected void SetupDisplayMode()
		{
			displayTagsArea = (HtmlGenericControl)TemplateContainer.FindControl("displayTagsArea");
			if (DisplayMode == TagFieldDisplayMode.Invisible)
			{
				AddHideControlJavascript(displayTagsArea.ClientID);
			}
			else if (ItemFieldValue != null && ListItem != null && SlamId != null)
			{
				ltDisplayTags.Text = String.Join(", ", ItemTagTreeNodes.Select(n => String.IsNullOrEmpty(n.Text) ? n.Identifier : n.Text).ToArray());
			}
		}

		protected void SetupInvisibleMode()
		{
			AddHideControlJavascript(editTagsArea.ClientID);
			if (ControlMode == SPControlMode.New || ItemFieldValue == null)
			{
				foreach (var tag in TagTree.FindNodes(n => n.Type == TagTreeNodeType.Tag))
				{
					if (Field.DefaultValue != null && tag.Identifier == Field.DefaultValue.Trim())
					{
						hdnSelectedTagIds.Value = tag.Tag.ListRelativeId.ToString();
						SetFieldControlValue(String.Format("{0};#{1}", tag.Tag.ListRelativeId, String.IsNullOrEmpty(tag.Text) ? tag.Identifier : tag.Text));
					}
				}
			}
			else
			{
				SPFieldLookupValueCollection currentValues = new SPFieldLookupValueCollection();
				foreach (var currentTagTreeNode in ItemTagTreeNodes)
				{
					hdnSelectedTagIds.Value += currentTagTreeNode.Tag.ListRelativeId.ToString() + ",";
				}
				hdnSelectedTagIds.Value = hdnSelectedTagIds.Value.TrimEnd(',');
			}
		}

		protected void FindControls()
		{
			ltDisplayTags = (Literal)TemplateContainer.FindControl("ltDisplayTags");
			editTagsArea = (HtmlGenericControl)TemplateContainer.FindControl("editTagsArea");
			pnlModalDisplay = (Panel)TemplateContainer.FindControl("pnlModalDisplay");
			pnlCheckboxDisplay = (Panel)TemplateContainer.FindControl("pnlCheckboxDisplay");
			pnlDropDownDisplay = (Panel)TemplateContainer.FindControl("pnlDropDownDisplay");
			tagListing = (HtmlGenericControl)TemplateContainer.FindControl("tagListing");
			editModalLink = (HtmlGenericControl)TemplateContainer.FindControl("editModalLink");
			tagModal = (HtmlGenericControl)TemplateContainer.FindControl("tagModal");
			tvTagHierarchy = (TagTreeView)TemplateContainer.FindControl("tvTagHierarchy");
			btnCancel = (Button)TemplateContainer.FindControl("btnCancel");
			btnOk = (Button)TemplateContainer.FindControl("btnOk");
			rptCheckList = (Repeater)TemplateContainer.FindControl("rptCheckList");
			ddlTags = (DropDownList)TemplateContainer.FindControl("ddlTags");
			errors = (HtmlGenericControl)TemplateContainer.FindControl("errors");
			hdnValueField = (HiddenField)TemplateContainer.FindControl("hdnValueField");
			editTags = (HtmlAnchor)TemplateContainer.FindControl("editTags");
			tagModalList = (HtmlGenericControl)TemplateContainer.FindControl("tagModalList");
			hdnDefaultValue = (HiddenField)TemplateContainer.FindControl("hdnDefaultValue");
			ltTitle = (Literal)TemplateContainer.FindControl("ltTitle");
			ltCategoryHandle = (Literal)TemplateContainer.FindControl("ltCategoryHandle");
			hdnSelectedTagIds = (HiddenField)TemplateContainer.FindControl("hdnSelectedTagIds");
		}

		protected override void CreateChildControls()
		{
			if (Field != null)
			{
				base.CreateChildControls();
				FindControls();

				AddCssIncludes();
				AddJavascriptIncludes();

				LoadSlamPropertiesForItem();

				if (ControlMode == SPControlMode.Display)
				{
					SetupDisplayMode();	
				}
				else if (ControlMode == SPControlMode.Edit || ControlMode == SPControlMode.New)
				{
					if (!base.IsFieldValueCached)
					{
						pnlModalDisplay.Visible = false;
						pnlCheckboxDisplay.Visible = false;
						pnlDropDownDisplay.Visible = false;

						if (!String.IsNullOrEmpty(TagCategoryId))
						{
							ltCategoryHandle.Text = "<span id=\"TagFieldCategory" + TagCategoryId + "\"></span>";

							if (!this.Page.IsPostBack && ControlMode == SPControlMode.Edit && SlamId != null)
							{	
								SPFieldLookupValueCollection currentValues = new SPFieldLookupValueCollection();
								foreach (var currentTagTreeNode in ItemTagTreeNodes)
								{
									currentValues.Add(new SPFieldLookupValue(currentTagTreeNode.Tag.ListRelativeId, String.IsNullOrEmpty(currentTagTreeNode.Text) ? currentTagTreeNode.Identifier : currentTagTreeNode.Text));
								}

								if (ItemFieldValue != null && ((string)ItemFieldValue).Length > 0 && ListItem.ModerationInformation.Status != SPModerationStatusType.Approved && currentValues.Count == 0 && ContentItem != null)
								{
									var contentItem = SlamCmsContext.Data.CreateQuery().FilterZone(Zone.ZoneId).FilterStatus(FilterStatus.LiveOrRetired).Cache(QueryCacheBehavior.NoCache).FilterContentItemId(SlamId.Replace("-p", "")).IncludeTags().Get().FirstOrDefault();
									if (contentItem != null)
									{
										string[] tagIdentifiers = contentItem.Tags.Select(t => t.Identifier).ToArray();
										if (tagIdentifiers.Length > 0)
										{
											_itemTagTreeNodes = TagTree.FindNodes(n => !String.IsNullOrEmpty(n.Identifier) ? n.Identifier.In(tagIdentifiers) : false);
										}

										foreach (var currentTagTreeNode in ItemTagTreeNodes)
										{
											currentValues.Add(new SPFieldLookupValue(currentTagTreeNode.Tag.ListRelativeId, String.IsNullOrEmpty(currentTagTreeNode.Text) ? currentTagTreeNode.Identifier : currentTagTreeNode.Text));
										}
									}
								}
								SetFieldControlValue(currentValues.ToString());
							}

							if (DisplayMode == TagFieldDisplayMode.Invisible)
							{
								SetupInvisibleMode();
							}
							else
							{
								SPFieldLookupValueCollection currentTags = new SPFieldLookupValueCollection(hdnValueField.Value);
								List<int> defaultTagIds = DefaultTagTreeNodes.Select(d => d.Tag.ListRelativeId).ToList();

								switch (DisplayMode)
								{
									case TagFieldDisplayMode.CheckBoxes:
										pnlCheckboxDisplay.Visible = true;

										rptCheckList.ItemDataBound += new RepeaterItemEventHandler(rptCheckList_ItemDataBound);

										if (!this.Page.IsPostBack)
										{
											ListItemCollection checkBoxItems = new ListItemCollection();

											foreach (var tagTreeNode in TagTree.Root.Children.FirstOrDefault().Children)
											{
												ListItem checkBoxItem = new ListItem(String.IsNullOrEmpty(tagTreeNode.Text) ? tagTreeNode.Identifier : tagTreeNode.Text, tagTreeNode.Tag.ListRelativeId.ToString());
												checkBoxItem.Selected = hdnValueField.Value.StartsWith(String.Format("{0};#", tagTreeNode.Tag.ListRelativeId.ToString())) || hdnValueField.Value.Contains(String.Format(";#{0};#", tagTreeNode.Tag.ListRelativeId.ToString()));
												checkBoxItem.Enabled = !tagTreeNode.Tag.RestrictAccess;

												if (Field.DefaultValue != null && (String.IsNullOrEmpty(tagTreeNode.Text) ? tagTreeNode.Identifier : tagTreeNode.Text) == Field.DefaultValue.Trim())
												{
													if (ControlMode == SPControlMode.New || ItemFieldValue == null)
													{
														checkBoxItem.Selected = true;
													}
													if (checkBoxItem.Selected && ((bool)((SlamField)Field).GetCustomPropertyValue("DefaultRequired")))
													{
														checkBoxItem.Enabled = false;
													}
												}

												if ((ControlMode == SPControlMode.New || ItemFieldValue == null) && defaultTagIds.Contains(tagTreeNode.Tag.ListRelativeId) && !checkBoxItem.Selected)
												{
													checkBoxItem.Selected = true;
												}

												if (ContentType.DefaultTags.Any(t => t.TagId == tagTreeNode.Tag.TagId))
												{
													checkBoxItem.Selected = true;
													checkBoxItem.Enabled = false;
												}
												
												if (checkBoxItem.Selected)
												{
													hdnSelectedTagIds.Value += checkBoxItem.Value + ",";
												}

												checkBoxItems.Add(checkBoxItem);
											}

											hdnSelectedTagIds.Value = hdnSelectedTagIds.Value.TrimEnd(',');

											rptCheckList.DataSource = checkBoxItems;
											rptCheckList.DataBind();
										}

										Page.ClientScript.RegisterStartupScript(GetType(), "setupSelectedValues" + hdnSelectedTagIds.ClientID, @"
										$(document).ready(function() {
											$('#" + pnlCheckboxDisplay.ClientID + @" input:even').click(function()
											{   
												var selectedValues = $('#" + hdnSelectedTagIds.ClientID + @"').val().split(',');
												var selectedValue = $('#" + hdnSelectedTagIds.ClientID + @"').val();

												if(this.checked)
												{
													var valueInput = new Array($(this).parents('div:first').find('input:odd').val());

													if(selectedValue != '') 
													{
														selectedValues = selectedValues.concat(valueInput);
													}
													else
													{
														selectedValues = new Array(valueInput);
													}
												}
												else
												{
													var valueInput = $(this).parents('div:first').find('input:odd').val();
													for(var i = 0; i < selectedValues.length; i++)
													{
														if(selectedValues[i] == valueInput)
														{
															selectedValues.splice(i, 1);
															break;
														}
													}
												}
											   
												$('#" + hdnSelectedTagIds.ClientID + @"').val(selectedValues.join(','));
												if(updateFeatureOnTagOptions) 
												{
													updateFeatureOnTagOptions(true);
												}
											}); 
										});
									", true);

										break;
									case TagFieldDisplayMode.DropDown:
										pnlDropDownDisplay.Visible = true;

										if (!this.Page.IsPostBack)
										{
											List<ListItem> options = new List<ListItem>();
											bool optionSelected = false;

											foreach (var tagTreeNode in TagTree.Root.Children.FirstOrDefault().Children)
											{
												ListItem option = new ListItem(String.IsNullOrEmpty(tagTreeNode.Text) ? tagTreeNode.Identifier : tagTreeNode.Text, tagTreeNode.Tag.ListRelativeId.ToString());
												if (!optionSelected)
												{
													option.Selected = hdnValueField.Value.StartsWith(String.Format("{0};#", tagTreeNode.Tag.ListRelativeId)) || hdnValueField.Value.Contains(String.Format(";#{0};#", tagTreeNode.Tag.ListRelativeId));
													optionSelected = option.Selected;
												}

												if (Field.DefaultValue != null && (String.IsNullOrEmpty(tagTreeNode.Text) ? tagTreeNode.Identifier : tagTreeNode.Text) == Field.DefaultValue.Trim())
												{
													if (ControlMode == SPControlMode.New || ItemFieldValue == null)
													{
														option.Selected = true;
														optionSelected = true;
													}

													if (option.Selected && ((bool)((SlamField)Field).GetCustomPropertyValue("DefaultRequired")))
													{
														ddlTags.Enabled = false;
													}
												}

												if ((ControlMode == SPControlMode.New || ItemFieldValue == null) && defaultTagIds.Contains(tagTreeNode.Tag.ListRelativeId) && !option.Selected)
												{
													option.Selected = true;
													optionSelected = true;
												}

												if (ContentType.DefaultTags.Any(t => t.TagId == tagTreeNode.Tag.TagId))
												{
													option.Selected = true;
													optionSelected = true;
													ddlTags.Enabled = false;
												}

												if (!tagTreeNode.Tag.RestrictAccess)
												{
													options.Add(option);
												}

												if (option.Selected)
												{
													hdnSelectedTagIds.Value = option.Value;
												}
											}

											ddlTags.Items.AddRange(options.ToArray());

											if (Field.Required)
											{
												ddlTags.Items.Insert(0, new ListItem("-- Select --"));
											}
										}

										Page.ClientScript.RegisterStartupScript(GetType(), "setupSelectedValues" + hdnSelectedTagIds.ClientID, @"
										$(document).ready(function() {
											$('#" + pnlDropDownDisplay.ClientID + @" select').change(function()
											{   
												$('#" + hdnSelectedTagIds.ClientID + @"').val($(this).val());
												if(updateFeatureOnTagOptions) 
												{
													updateFeatureOnTagOptions(true);
												}
											}); 
										});
									", true);
										break;
									default:
										pnlModalDisplay.Visible = true;
										ltTitle.Text = "Edit " + Field.Title;

										if (!this.Page.IsPostBack)
										{
											TagTreeNode node = null;
											string matchedValues = "";

											foreach (var tagTreeNode in TagTree.FindNodes(n => n.Type == TagTreeNodeType.Tag))
											{
												node = new TagTreeNode(String.IsNullOrEmpty(tagTreeNode.Text) ? tagTreeNode.Identifier : tagTreeNode.Text, tagTreeNode.Tag.ListRelativeId.ToString());
												node.SelectAction = TreeNodeSelectAction.None;
												node.Enabled = !tagTreeNode.Tag.RestrictAccess;

												if (tagTreeNode.Parent.Type == TagTreeNodeType.Tag)
												{
													TagTreeNode parentNode = (TagTreeNode)tvTagHierarchy.FindChildNode(tagTreeNode.Parent.Tag.ListRelativeId.ToString());
													if (parentNode != null)
													{
														parentNode.ChildNodes.Add(node);
													}
													else
													{
														tvTagHierarchy.Nodes.Add(node);
													}
												}
												else
												{
													tvTagHierarchy.Nodes.Add(node);
												}

												node.Checked = hdnValueField.Value.StartsWith(String.Format("{0};#", tagTreeNode.Tag.ListRelativeId)) || hdnValueField.Value.Contains(String.Format(";#{0};#", tagTreeNode.Tag.ListRelativeId));

												if (Field.DefaultValue != null && (String.IsNullOrEmpty(tagTreeNode.Text) ? tagTreeNode.Identifier : tagTreeNode.Text) == Field.DefaultValue.Trim())
												{
													if (ControlMode == SPControlMode.New || ItemFieldValue == null)
													{
														node.Checked = true;
													}

													if (node.Checked && ((bool)((SlamField)Field).GetCustomPropertyValue("DefaultRequired")))
													{
														hdnDefaultValue.Value += Field.DefaultValue + ",";
													}
												}

												if ((ControlMode == SPControlMode.New || ItemFieldValue == null) && defaultTagIds.Contains(tagTreeNode.Tag.ListRelativeId) && !node.Checked)
												{
													node.Checked = true;
													hdnDefaultValue.Value += (String.IsNullOrEmpty(tagTreeNode.Text) ? tagTreeNode.Tag.Identifier : tagTreeNode.Text) + ",";
												}

												var defaultContentTypeTag = ContentType.DefaultTags.Where(t => t.TagId == tagTreeNode.Tag.TagId).FirstOrDefault();
												if (defaultContentTypeTag != null)
												{
													var defaultTagTreeNode = TagTree.FindNode(n => n.Type == TagTreeNodeType.Tag && n.Tag.TagId == defaultContentTypeTag.TagId);
													node.Checked = true;
													hdnDefaultValue.Value += (String.IsNullOrEmpty(defaultTagTreeNode.Text) ? defaultTagTreeNode.Tag.Identifier : defaultTagTreeNode.Text) + ",";
												}

												if (node.Checked)
												{
													matchedValues += String.Format(";#{0};#{1}", tagTreeNode.Tag.ListRelativeId, String.IsNullOrEmpty(tagTreeNode.Text) ? tagTreeNode.Identifier : tagTreeNode.Text);
													matchedValues = matchedValues.TrimStart(';', '#');
													hdnSelectedTagIds.Value += node.Value + ",";
													node.Expand();
												}
												else
												{
													node.CollapseAll();
												}
											}
											hdnValueField.Value = matchedValues;


											hdnSelectedTagIds.Value = hdnSelectedTagIds.Value.TrimEnd(',');
											tagListing.InnerHtml = Convert.ToString(Value);

											if (String.IsNullOrEmpty(tagListing.InnerHtml))
											{
												tagListing.InnerHtml = "&nbsp;&nbsp;&nbsp;";
											}

											bool treeIsOneLevel = true;
											foreach (TreeNode treeNode in tvTagHierarchy.Nodes)
											{
												if (treeNode.ChildNodes.Count > 0)
												{
													treeIsOneLevel = false;
													break;
												}
											}

											tvTagHierarchy.NodeStyle.CssClass = "tag-list-item";
											tvTagHierarchy.ParentNodeStyle.CssClass = "tag-list-parent-item";
											tvTagHierarchy.ShowExpandCollapse = !treeIsOneLevel;
											tvTagHierarchy.ShowCheckBoxes = TreeNodeTypes.All;
											tvTagHierarchy.ShowLines = !treeIsOneLevel;
										}

										if (DisplayMode == TagFieldDisplayMode.Modal)
										{	
											Page.ClientScript.RegisterClientScriptInclude("jquery.blockUI", ResolveUrl("~/_layouts/inc/jquery.blockUI.js"));
											if (!Page.ClientScript.IsStartupScriptRegistered("setupModal" + tagModal.ClientID))
											{
												Page.ClientScript.RegisterStartupScript(GetType(), "setupModal" + tagModal.ClientID, @"
												var " + tagModal.ClientID.TrimStart('#') + @"Selections = '';
												$(document).ready(function() {
													$.blockUI.defaults.css = {};
													$.blockUI.defaults.fadeIn = 0;
													$.blockUI.defaults.fadeOut = 0;
													$('#" + tagModalList.ClientID + @" a').click(function() { return false; } );

													$('#" + tagModalList.ClientID + @" input:even').click(function()
													{   
														if(this.checked)
														{   
															var parents = $(this).parents('div:first').prev('table').find('input:even');
															for(var i = 0; i < parents.length; i++)
															{
																if(!parents[i].checked)
																{   
																	parents[i].checked = true;
																	setParentCheck(parents[i]);
																}
															}
														}
														else
														{
															var children = $(this).parents('table:first').next('div').find('input:even');
															for(var i = 0; i < children.length; i++)
															{
																if(children[i].checked)
																{
																	children[i].checked = false;
																}
															}
														}

														eval($(this).parents('table:first').find('a:first').attr('href'));
													}); 

													function setParentCheck(parent)
													{
														if(parent.checked)
														{
															var parents = $(parent).parents('div:first').prev('table').find('input:even');
															for(var i = 0; i < parents.length; i++)
															{
																if(!parents[i].checked)
																{   
																	parents[i].checked = true;
																	setParentCheck(parents[i]);
																}
															}
														}
													}
													$('#" + editTags.ClientID + @"').click(function() {
														var defaultValue = '" + hdnDefaultValue.Value + @"';
														var checkBoxes = $('#" + tagModalList.ClientID + @" input:even');
														var names = $('#" + tagModalList.ClientID + @" span');
														var enabledFlags = $('#" + tagModalList.ClientID + @" input:odd');
																											   
														for(var c = 0; c < checkBoxes.length; c++)
														{
															" + tagModal.ClientID.TrimStart('#') + @"Selections += checkBoxes[c].checked + ',';
														
															if(defaultValue.indexOf(names[c].innerHTML + ',') > -1)
															{   
																checkBoxes[c].disabled = true;
															} 
															if(enabledFlags[c].value.toLowerCase().indexOf('false') > -1)
															{
																checkBoxes[c].disabled = true;
															}
														}
														if(" + tagModal.ClientID.TrimStart('#') + @"Selections.length > 0)
														{
															" + tagModal.ClientID.TrimStart('#') + @"Selections = " + tagModal.ClientID.TrimStart('#') + @"Selections.substr(0, " + tagModal.ClientID.TrimStart('#') + @"Selections.length - 1);
														}
														$.blockUI({ message: $('#" + tagModal.ClientID + @"') });
													});

//													var defaultValue = '" + hdnDefaultValue.Value + @"';
//													var names = $('#" + tagModalList.ClientID + @" span');
//													var defaultCheckBoxes = $('#" + tagModalList.ClientID + @" input:even');
//													var enabledFlags = $('#" + tagModalList.ClientID + @" input:odd');
//													for(var i = 0; i < defaultCheckBoxes.length; i++)
//													{
//														if(defaultValue.indexOf(names[i].innerHTML + ',') > -1)
//														{
//															defaultCheckBoxes[i].disabled = true;
//														}
//
//														if(enabledFlags[i].value.toLowerCase().indexOf('false') > -1)
//														{
//															defaultCheckBoxes[i].disabled = true;
//														}
//													}
												});
											", true);
											}
											btnOk.OnClientClick = @"$.unblockUI({ onUnblock:
											function()
											{
												var checkBoxes = $('#" + tagModalList.ClientID + @" input:even');
												var values = $('#" + tagModalList.ClientID + @" input:odd');
												var names = $('#" + tagModalList.ClientID + @" span');
												var selectedTags = '';
												var selectedValues = '';
												for(var c = 0; c < checkBoxes.length; c++)
												{
													if(checkBoxes[c].checked)
													{   
														selectedTags = selectedTags + names[c].innerHTML + ', ';
														selectedValues = selectedValues + values[c].value.split(',')[0] + ',';
													}
													checkBoxes[c].disabled = false;
												}
												if(selectedValues.length > 0)
												{   
													selectedValues = selectedValues.substr(0, selectedValues.length - 1);
												}
												if(selectedTags.length > 0)
												{   
													selectedTags = selectedTags.substr(0, selectedTags.length - 2);
												}
												else
												{
													selectedTags = '&nbsp;&nbsp;&nbsp;';
												}
												$('#" + tagListing.ClientID + @"').html(selectedTags);
												" + tagModal.ClientID.TrimStart('#') + @"Selections = '';
												$('#" + hdnSelectedTagIds.ClientID + @"').val(selectedValues);

												if(updateFeatureOnTagOptions) 
												{
													updateFeatureOnTagOptions(true);
												}
											}
										}); return false";

											btnOk.UseSubmitBehavior = false;
											btnOk.CausesValidation = false;

											btnCancel.OnClientClick = @"$.unblockUI({ onUnblock:
											function()
											{
												var checkBoxes = $('#" + tagModalList.ClientID + @" input:even');
												var selections = " + tagModal.ClientID.TrimStart('#') + @"Selections.split(',');
												for(var c = 0; c < checkBoxes.length; c++)
												{
													checkBoxes[c].checked = (selections[c] == 'true');
													checkBoxes[c].disabled = false;
												}
												" + tagModal.ClientID.TrimStart('#') + @" = '';
											}
										}); return false";

											btnCancel.UseSubmitBehavior = false;
											btnCancel.CausesValidation = false;
										}
										else
										{
											editModalLink.Visible = false;
										}

										break;
								}
							}
						}
					}
				}
			}
		}

		protected void rptCheckList_ItemDataBound(object sender, RepeaterItemEventArgs e)
		{
			if (e.Item != null && (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem))
			{
				ListItem currentItem = (ListItem)e.Item.DataItem;
				CheckBox chkTag = e.Item.FindControl("chkTag") as CheckBox;
				HiddenField chkTagValue = e.Item.FindControl("chkTagValue") as HiddenField;
				chkTag.Checked = currentItem.Selected;
				chkTag.Enabled = currentItem.Enabled;
				chkTag.Text = currentItem.Text;
				chkTagValue.Value = currentItem.Value;
			}
		}
	}
}